package doctorpack;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.media.*;
import javax.media.protocol.*;
import javax.media.format.*;
import javax.media.control.*;
import javax.media.datasink.*;

/*
*
* Lindoélio Lázaro
*
*/

public class webcam extends JFrame {

   private JButton captureButton;
   private Component progressoGravacao;
   private Format formats[], formatoSelecionado;
   private FormatControl controlesFormato[];
   private CaptureDeviceInfo informacoesDispositivo;
   private Vector dispositivosLista;
   private DataSource inSource, saida;
   private DataSink dataSink;
   private Processor processor;

   public webcam() {
      super( "Captura..." );
      JPanel buttonPanel = new JPanel();
      getContentPane().add( buttonPanel );
      captureButton = new JButton( "Capturar e Salvar" );
      buttonPanel.add( captureButton, BorderLayout.CENTER );
      captureButton.addActionListener( new CaptureHandler() );
      Manager.setHint( Manager.LIGHTWEIGHT_RENDERER, Boolean.TRUE );
      addWindowListener(
         new WindowAdapter() {
            public void windowClosing( WindowEvent windowEvent ) {
               if ( processor != null )
                  processor.close();
            }
         }
      );
   }

   private class CaptureHandler implements ActionListener {
      public void actionPerformed( ActionEvent actionEvent ) {
         dispositivosLista = CaptureDeviceManager.getDeviceList( null );
         if ((dispositivosLista == null) || (dispositivosLista.size() == 0)) {
            informarErro( "Nenhum dispositivo de captura encontrado!" );
            return;
         }

         // lista todos os dispositivos encontrados
         String nomesDispositivos[] = new String[dispositivosLista.size()];
         for ( int i = 0; i < dispositivosLista.size(); i++){
            informacoesDispositivo = (CaptureDeviceInfo)dispositivosLista.elementAt(i);
            nomesDispositivos[i] = informacoesDispositivo.getName();
         }
         int indiceDispositivoSelecionado = capturarIndiceDispositivoSelecionado(nomesDispositivos);

         if (indiceDispositivoSelecionado == -1)
            return;

         // pega informações do dispositivo selecionado
         informacoesDispositivo = (CaptureDeviceInfo)dispositivosLista.elementAt(indiceDispositivoSelecionado);
         formats = informacoesDispositivo.getFormats();
         
         if (inSource != null)
            inSource.disconnect();
         
         try {
            inSource = Manager.createDataSource(informacoesDispositivo.getLocator());
            controlesFormato = ((CaptureDevice)inSource).getFormatControls();
            formatoSelecionado = capturarFormatoSelecionado(formats);
            if (formatoSelecionado == null)
               return;
            mostrarFormatoDispositivo(formatoSelecionado);
            captureSaveFile();
         }
         catch (NoDataSourceException noData) {
            noData.printStackTrace();
         }
         catch (IOException io) {
            io.printStackTrace();
         }
      }
   }

   public void mostrarFormatoDispositivo(Format formatoAtual) {
      for (int i = 0; i < controlesFormato.length; i++) {
         if (controlesFormato[i].isEnabled() ) {
            controlesFormato[i].setFormat(formatoAtual);
            System.out.println ("Formato atualmente como "+controlesFormato[i].getFormat() );
         }
      }
   }

   public int capturarIndiceDispositivoSelecionado(String[] names) {
      String name = (String) JOptionPane.showInputDialog(this, "Selecione um dispositivo: ", "Dispositivo",
                    JOptionPane.QUESTION_MESSAGE,
                    null,
                    names,
                    names[0]);
      if (name != null)
         return Arrays.binarySearch(names, name);
      else
         return -1;
   }

   public Format capturarFormatoSelecionado(Format[] formatosLista) {
      return (Format) JOptionPane.showInputDialog(this,"Selecione um formato: ", "Formatos suportados",
         JOptionPane.QUESTION_MESSAGE,
         null,
         formatosLista,
         null);
   }

   public void informarErro(String error) {
      JOptionPane.showMessageDialog(this, error, "Informação", JOptionPane.ERROR_MESSAGE);
   }

   public File capturarArquivoSalvo() {
      JFileChooser fileChooser = new JFileChooser();
      fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
      int resultado = fileChooser.showSaveDialog(this);
      if (resultado == JFileChooser.CANCEL_OPTION)
         return null;
      else
         return fileChooser.getSelectedFile();
   }

   public void showSaveMonitor() {
      int result = JOptionPane.showConfirmDialog(this,progressoGravacao, "Capturando...",
         JOptionPane.DEFAULT_OPTION,
         JOptionPane.PLAIN_MESSAGE);
      
      if ((result == JOptionPane.OK_OPTION) || (result == JOptionPane.CLOSED_OPTION)) {
         processor.stop();
         processor.close();
         JOptionPane.showMessageDialog(this,"Captura salva com sucesso!");
      }
   }

   public void captureSaveFile() {
      Format outFormats[] = new Format[1];
      outFormats[0] = formatoSelecionado;
      FileTypeDescriptor outFileType = new FileTypeDescriptor(FileTypeDescriptor.MSVIDEO);
      try {
         processor = Manager.createRealizedProcessor(new ProcessorModel(inSource, outFormats, outFileType));
         if (!gravarDados())
            return;
         processor.start();
         MonitorControl controles = (MonitorControl)processor.getControl("javax.media.control.MonitorControl");
         progressoGravacao = controles.getControlComponent();
         showSaveMonitor();
      }
      catch (NoProcessorException noProcessor) {
         noProcessor.printStackTrace();
      }
      catch (CannotRealizeException cannotRealize) {
         cannotRealize.printStackTrace();
      }
      catch (IOException ioException) {
         ioException.printStackTrace();
      }
   }

   public boolean gravarDados() {
      File arquivoSalvo = capturarArquivoSalvo();
      
      if (arquivoSalvo == null)
         return false;
      saida = processor.getDataOutput();
      
      if (saida == null) {
         informarErro("Sem saída para processar!");
         return false;
      }
      try {
         MediaLocator localizacaoArquivo = new MediaLocator(arquivoSalvo.toURL());
         dataSink = Manager.createDataSink(saida, localizacaoArquivo);
         dataSink.addDataSinkListener(new DataSinkListener() {
             public void dataSinkUpdate(DataSinkEvent dataEvent) {
                 if (dataEvent instanceof EndOfStreamEvent)
                     dataSink.close();
                 }
             }
         );
         dataSink.open();
         dataSink.start();
      }
      catch ( NoDataSinkException noDataSinkException ) {
         noDataSinkException.printStackTrace();
         return false;
      }
      catch ( SecurityException securityException ) {
         securityException.printStackTrace();
         return false;
      }
      catch ( IOException ioException ) {
         ioException.printStackTrace();
         return false;
      }
      return true;
   }
}
